<?php
/**********************
**user.inc
**Date Created: 4/13/2009
**Copyright 2009 Tomorrow Tech Industries
**Contact: RPITomorrowTech@gmail.com
**********************/

require_once("private/dba.inc");
require_once("private/login.inc");

define('USERNAME_MAX_LENGTH', 24);

class User
{
    //member declarations
    private $username = '';

	//static member declarations
	static $lastError = '';

    // method declaration
	
	public function User($username, &$rc)
	{
		$this->username = $username;
		
		//Do a sanity check
		$rc = User::usernameTaken($username, $isTaken);
		if( TT_FAILED($rc) )
		{
			return;
		}
		//Fail construction if the user doesn't exist
		if( !$isTaken )
		{
			User::setLastError("User does not exist");
			$rc = TT_GENERAL;
			return;
		}
		
		//Otherwise we are clear
		$rc = TT_OK;
	}
	
	//Should be instance?  We may wish to salt it later
	public static function computeHash($password)
	{
		return md5($password);
	}
	
	public function isPasswordCorrect($passwordIn)
	{
		return $this->isPasswordCorrectByHash($this->computeHash($passwordIn));
	}

	//Returns TT_ACCESS if password is not correct
	public function isPasswordCorrectByHash($hashIn)
	{
		$rc = $this->getPassword($correctHash);
		if( TT_FAILED($rc) )
		{
			return $rc;
		}
		//Password is correct if hashes match
		if( $correctHash == $hashIn )
		{
			return TT_OK;
		}
		else
		{
			//Hashes do not match, return access denied
			return TT_ACCESS;
		}
	}
			
	//Print out the user
	public function PrintUser()
	{
		echo $this->getName() . ", " . $this->getUserName() . ",  etc";
	}

	//These function are used by the User Class.
	//User Class Helper Functions
	//These update functions will be written later.  They are mainly for use in the Edit Profile usecase.
	public function getUsername(&$username)
	{
		$username = $this->username;
		return TT_OK;
	}

	public function setUsername($username)
	{
		return $this->setColumn("username", DBaccess::GetSQLValueString($username, 'text'));
	}

	public function getPassword(&$password)
	{
		return $this->getColumn("password", $password);
	}

	public function setPassword($password)
	{
		return $this->setColumn("password", DBaccess::GetSQLValueString(md5($password), 'text'));
	}

	public function getName(&$name)
	{
		return $this->getColumn("name", $name);
	}

	public function setName($name)
	{
		return $this->setColumn("name", DBaccess::GetSQLValueString($name, 'int'));
	}

	public function getAccessGroup(&$accessGroup)
	{
		return $this->getColumn("accessGroup", $accessGroup);
	}

	public function setAccessGroup($accessGroup)
	{
		return $this->setColumn("accessGroup", DBaccess::GetSQLValueString($accessGroup, 'text'));
	}
	

	//Utility functions
	
	//All get requests are essentially the same
	//Get a single column value matching the current username
	private function getColumn($column, &$value)
	{
		//There should only be a single username
		$q = "SELECT $column FROM User WHERE username='{$this->username}' LIMIT 1";
		$db = new DBaccess(); 
		$rc = $db->executeQuery($q, $result);
		if( TT_FAILED($rc) )
		{
			User::setLastError("Couldn't execute query: " . $q);
			return $rc;
		}
		$row = mysql_fetch_array($result);
		$value = $row[0];
		return TT_OK;
	}
		
	//All set requests are essentially the same
	//Update a single column matching the current username id to a certain value
	//Value must already be escaped prior to entering this function
	private function setColumn($column, $value)
	{
		//There should only be a single username
		//Example: the following are equivilent:
		$q = "UPDATE User SET $column=$value WHERE username={$this->username} LIMIT 1";
		$db = new DBaccess(); 
		$rc = $db->executeQuery($q, $result);
		if( TT_FAILED($rc) )
		{
			User::setLastError("DB error: " . $db->getLastError() . ", query: " . $q);
			return $rc;
		}

		return TT_OK;
	}

	/********
	Static functions
	********/
	
	/**
	 * Returns true if the username has been taken
	 * by another user, false otherwise.
	 */
	static public function usernameTaken($username, &$isTaken)
	{
		//Escape
		$username = DBaccess::GetSQLValueString($username, 'text');
		
		$q = "SELECT COUNT(*) FROM User WHERE username=" . $username;
		$db = new DBaccess(); 
		$rc = $db->executeQuery($q, $result);
		if( TT_FAILED($rc) )
		{
			User::setLastError("Couldn't execute query: " . $q);
			return $rc;
		}
		$row = mysql_fetch_array($result);
		//Really this should not be more than one
		$isTaken = $row[0] > 0;
		return TT_OK;
	}

	public static function createNewUser(&$user, $fields)
	{
		if( !isset($fields['username']) )
		{
			return TT_INVALID_INPUT;
		}
		$username = $fields['username'];
		//Don't duplicate user names
		if( TT_FAILED(User::usernameTaken($username, $isTaken)) )
		{
			return TT_GENERAL;
		}
		if( $isTaken )
		{
			return TT_INVALID_INPUT;
		}
		
		if( !isset($fields['password']) )
		{
			return TT_INVALID_INPUT;
		}
		$password = $fields['password'];

		if( !isset($fields['name']) )
		{
			return TT_INVALID_INPUT;
		}
		$name = $fields['name'];

		if( !isset($fields['accessGroup']) )
		{
			return TT_INVALID_INPUT;
		}
		$accessGroup = $fields['accessGroup'];

		//We need this unescaped later
		$usernameOrig = $username;
		
		//Escape the values
		$username = DBaccess::GetSQLValueString($username, 'text');
		$name = DBaccess::GetSQLValueString($name, 'text');
		$accessGroup = DBaccess::GetSQLValueString($accessGroup, 'int');
		//We must store this unescaped for session use
		$md5pass = md5($password);
		//Password itself is NOT escaped since its hashed
		$password = DBaccess::GetSQLValueString($md5pass, 'text');

		//id is auto-incremented to form its value
		$q = "INSERT INTO User(username, password, name, accessGroup) VALUES($username, $password, $name, $accessGroup)";
		$db = new DBaccess(); 
		$rc = $db->executeQuery($q, $result);
		if( TT_FAILED($rc) )
		{
			User::setLastError("Couldn't execute query: " . $q);
			return $rc;
		}
		//Give a handle to the newly created user
		$user = new User($usernameOrig, $rc);
		return $rc;
	}
	
	//Debug functions

	public static function getLastError()
	{
		return User::$lastError;
	}
	
	public static function clearLastError()
	{
		User::$lastError = '';
	}
	
	protected static function setLastError($error)
	{
		User::$lastError = $error;
	}
}
//End of User Class


?>
